package com.globaldom.utils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import com.globaldom.model.CountryDetail;
import com.globaldom.model.PersonLocation;
import com.globaldom.model.Research;
import com.globaldom.model.Sales;
import com.globaldom.model.Science;
import com.globaldom.model.Stats;
import com.google.appengine.api.memcache.Expiration;
import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;

@SuppressWarnings("unchecked")
public class MemCacheManager {

	private static final Logger log = Logger.getLogger(MemCacheManager.class.getName());

	private static final MemcacheService memcache = MemcacheServiceFactory.getMemcacheService();
	private static final String _deployment = "dep";
	private static final String _combatant = "enemy";
	private static final String _locations = "locs";
	private static final String _notifications = "notes";
	private static final String _allsales = "allsales";
	private static final String _civresources = "civs";
	private static final String _milresources = "mils";
	private static final String _homelocation = "home";
	private static final String _homedeployment = "homedep";
	private static final String _stats = "stats";
	private static final String _countrystats = "countrystats";
	private static final String _authstats = "authstats";
	private static final String _countries = "countries";
	private static final String _science = "sciences";
	private static final String _research = "research";
	private static final String _distance = "distance";
	/*
	 * Personal Stats
	 */

	public static Long getPersonalStats(String personId) {
		Object cacheObject = memcache.get(_stats);
		if (cacheObject != null) {
			Map<Long, Long> statsMap = (Map<Long, Long>) cacheObject;
			return statsMap.get(personId);
		}
		return null;
	}

	public static Map<Long, Long> getAllPersonalStats() {
		Object cacheObject = memcache.get(_stats);
		if (cacheObject != null) {
			Map<Long, Long> statsMap = (Map<Long, Long>) cacheObject;
			return statsMap;

		}
		return null;
	}

	/*
	 * Too complicated code for memory manager!
	 */
	public static void putStats(String personId, Long dollarValue) {

		try {
			Object cacheObject = memcache.get(_stats);
			boolean addNow = true;

			Map<String, Long> statsMap;
			if (cacheObject != null) {

				statsMap = (Map<String, Long>) cacheObject;
				List<Long> c = new ArrayList<Long>((Collection<Long>) statsMap.values());
				Collections.sort(c);
				if (c.size() > 10) {
					if ((Long) c.get(0) < dollarValue) {
						c.remove(0);
						statsMap.put(personId, dollarValue);
						addNow = true;
					}

				} else {
					statsMap.put(personId, dollarValue);
					addNow = true;
				}

			} else {
				statsMap = new HashMap<String, Long>();
				statsMap.put(personId, dollarValue);
				addNow = true;
			}

			if (addNow) {
				memcache.put(_stats, statsMap, Expiration.byDeltaSeconds(18600));
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}

	}

	public static void removeStats() {
		memcache.delete(_stats);
	}

	
	/*
	 * Auth Stats
	 */

	public static Map<String,Object> getAuthStats(String sessionID) {
		Object cacheObject = memcache.get(_authstats + sessionID);
		if (cacheObject != null)
			return (Map<String,Object>) cacheObject;
		return null;
	}

	public static void putAuthStats(String sessionID, Map<String,Object> auths) {
		memcache.put(_authstats + sessionID, auths, Expiration.byDeltaSeconds(18600));
	}

	public static void removeAuths(String cid) {
		memcache.delete(_authstats + cid);
	}
	
	/*
	 * Country Stats
	 */

	public static Stats getCountryStats(String cid) {
		Object cacheObject = memcache.get(_countrystats + cid);
		if (cacheObject != null)
			return (Stats) cacheObject;
		return null;
	}

	public static void putCountryStats(String cid, Stats stats) {
		memcache.put(_countrystats + cid, stats, Expiration.byDeltaSeconds(18600));
	}

	public static void removeCountryStats(String cid) {
		memcache.delete(_countrystats + cid);
	}

	/*
	 * NOTIFICATIONS
	 */

	public static List<Notifications> getNotifications(String personID) {
		Object cacheObject = memcache.get(_notifications + personID);
		if (cacheObject != null)
			return (List<Notifications>) cacheObject;
		return null;
	}

	public static void putNotification(String personID, List<Notifications> notices) {
		memcache.put(_notifications + personID, notices, Expiration.byDeltaSeconds(18600));
	}

	public static void removeNotification(String personID) {
		memcache.delete(_notifications + personID);
	}

	public static void addNotification(String receipient, Notifications notice) {

		Object cacheObject = memcache.get(_notifications + receipient);
		List<Notifications> notices;
		if (cacheObject == null) {
			notices = new ArrayList<Notifications>();
		} else {
			notices = (List<Notifications>) cacheObject;
		}
		notices.add(notice);
		putNotification(receipient, notices);

	}

	/*
	 * PERSONAL SALES
	 */

	public static Map<String, String> getMySales(String personalID) {
		Object cacheObject = memcache.get(_allsales + personalID);
		if (cacheObject != null)
			return (Map<String, String>) cacheObject;
		return null;
	}

	public static void putinMySales(Map<String, String> sales, String PersonID) {
		memcache.put(_allsales + PersonID, sales, Expiration.byDeltaSeconds(1800));
	}

	public static void removeMySales(String personID) {
		memcache.delete(_allsales + personID);
	}

	public static void addMySale(Sales sale, String personID) {

		Object cacheObject = memcache.get(_allsales + personID);
		Map<String, String> salesMap;
		if (cacheObject == null) {
			salesMap = new HashMap<String, String>();
		} else {
			salesMap = ((Map<String, String>) cacheObject);
		}
		salesMap.put(sale.getPerson() + "/" + sale.getId(), sale.getSaleType() + "/" + sale.getSaleAmount() + "/"
				+ sale.getSalePrice());
		putinMySales(salesMap, personID);

	}

	/*
	 * HOME DEPLOYMENT
	 */

	public static Map<Integer, Long> getFreeResources(String personid) {
		Object cacheObject = memcache.get(_homedeployment + personid);
		if (cacheObject != null)
			return (Map<Integer, Long>) cacheObject;
		return null;
	}

	public static void putFreeResources(String personid, Map<Integer, Long> deployments) {
		memcache.put(_homedeployment + personid, deployments, Expiration.byDeltaSeconds(3600));
	}

	public static void removeFreeResources(String personid) {
		memcache.delete(_homedeployment + personid);
	}

	

	/*
	 * DEPLOYMENT
	 */

	public static Map<Integer, Long> getDeployment(String personid, String locid) {
		Object cacheObject = memcache.get(_deployment + locid + personid);
		if (cacheObject != null)
			return (Map<Integer, Long>) cacheObject;
		return null;
	}

	public static void putDeployment(String personid, String locid, Map<Integer, Long> deployments) {
		memcache.put(_deployment + locid + personid, deployments, Expiration.byDeltaSeconds(3600));
	}

	public static void removeDeployments(String personid, String locid) {
		memcache.delete(_deployment + locid + personid);
	}

	public static void addDeployment(String personid, String locid, String coords) {
		throw new RuntimeException("Not Implemented!");
	}

	/*
	 * DISTANCE
	 */

	public static  Integer getDistance(String personid, String locid) {
		Object cacheObject = memcache.get(_distance + locid + personid);
		if (cacheObject != null)
			return (Integer) cacheObject;
		return null;
	}

	public static void putDistance(String personid, String locid, Integer distance) {
		memcache.put(_distance + locid + personid, distance, Expiration.byDeltaSeconds(3600));
	}

	public static void removeDistance(String personid, String locid) {
		memcache.delete(_distance + locid + personid);
	}

	
	/*
	 * COMBATANTS
	 */

	public static Map<String, String> getCombatants(String personid) {
		Object cacheObject = memcache.get(_combatant + personid);
		if (cacheObject != null)
			return (Map<String, String>) cacheObject;
		return null;
	}

	public static void putCombatants(String personid, Map<String, String> locations) {
		memcache.put(_combatant + personid, locations, Expiration.byDeltaSeconds(3600));
	}

	public static void removeCombatants(String personid) {
		memcache.delete(_combatant + personid);
	}

	@Deprecated
	public static void addCombatant(String personid, String locid, String coords) {
		Object cacheObject = memcache.get(_combatant + personid);
		if (cacheObject != null) {
			((Map<String, String>) cacheObject).put(locid, coords);
		}

	}

	/*
	 * LOCATIONS
	 */

	public static Map<String, String> getLocations(String personid) {
		Object cacheObject = memcache.get(_locations + personid);
		if (cacheObject != null)
			return (Map<String, String>) cacheObject;
		return null;
	}

	public static void putLocations(String personid, Map<String, String> locations) {
		memcache.put(_locations + personid, locations, Expiration.byDeltaSeconds(9600));
	}

	public static void removeLocations(String personid) {
		memcache.delete(_locations + personid);
	}

	public static void addLocation(String personid, String locid, String coords) {
		Object cacheObject = memcache.get(_locations + personid);
		Map<String, String> locMap;
		if (cacheObject == null) {
			locMap = new HashMap<String, String>();
		} else {
			locMap = ((Map<String, String>) cacheObject);
		}
		locMap.put(locid, coords);
		putLocations(personid, locMap);

	}

	public static void addLocation(String personid, PersonLocation location) {

		if (null == location.getId()) {
			// PURGE THE CACHE?
			removeLocations(personid);
			return;
		}

		Object cacheObject = memcache.get(_locations + personid);
		Map<String, String> locMap;
		if (cacheObject == null) {
			locMap = new HashMap<String, String>();
		} else {
			locMap = ((Map<String, String>) cacheObject);
		}

		String locid = location.getId().toString();
		String cords = location.getLatitude() + "/" + location.getLongitude();
		locMap.put(locid, cords);
		putLocations(personid, locMap);

		// Add in the global database too?

	}

	public static void removeLocation(String personid, PersonLocation location) {
		Object cacheObject = memcache.get(_locations + personid);
		if (cacheObject != null) {
			if (null == location.getId()) {
				// PURGE THE CACHE. Fail fast!
				removeLocations(personid);
				return;
			}
			String locid = location.getId().toString();
			removeLocation( personid,locid);
		}

	}

	public static void removeLocation(String personid, String locationid) {
		Object cacheObject = memcache.get(_locations + personid);
		if (cacheObject != null) {
			Map<String, String> locMap = ((Map<String, String>) cacheObject);
			locMap.remove((String.valueOf(locationid)));
			putLocations(personid, locMap);
		}

	}

	/*
	 * RESEARCH
	 */

	public static List<Research> getResearch(String personid) {
		Object cacheObject = memcache.get(_research + personid);
		if (cacheObject != null)
			return (List<Research>) cacheObject;
		return null;
	}

	public static void putResearch(String personid, List<Research> research) {
		memcache.put(_research + personid, research, Expiration.byDeltaSeconds(36000));
	}

	public static void removeResearch(String personid) {
		memcache.delete(_research + personid);
	}

	public static void addResearch(String personid, Research research) {
		Object cacheObject = memcache.get(_research + personid);
		if (cacheObject != null) {

			List<Research> researches = (List<Research>) cacheObject;
			researches.add(research);
			putResearch(personid, researches);

		}

	}

	/*
	 * CIVILIANS
	 */

	public static Map<String, String> getCivics(String personid) {
		Object cacheObject = memcache.get(_civresources + personid);
		if (cacheObject != null)
			return (Map<String, String>) cacheObject;
		return null;
	}

	public static void putCivics(String personid, Map<String, String> civics) {
		memcache.put(_civresources + personid, civics, Expiration.byDeltaSeconds(3600));
	}

	public static void removeCivics(String personid) {
		memcache.delete(_civresources + personid);
	}

	public static void addCivic(String personid, Integer civType, Long resAmount) {
		Object cacheObject = memcache.get(_civresources + personid);
		if (cacheObject != null) {

			Map<String, String> civiMap = ((Map<String, String>) cacheObject);
			civiMap.put("res" + civType, String.valueOf(resAmount));
			putCivics(personid, civiMap);

		}

	}

	/*
	 * ALL SCIENCE
	 */

	public static List<Science> getAllScience() {
		Object cacheObject = memcache.get(_science);
		return cacheObject != null ? (List<Science>) cacheObject : null;

	}

	public static void putScience(List<Science> sciences) {
		try {

			memcache.put(_science, sciences, Expiration.byDeltaSeconds(6000));
		} catch (Exception ex) {
			log.severe("Error attempting to store science!");
		}
	}

	public static void removeScience() {
		memcache.delete(_science);
	}

	/*
	 * ALL COUNTRIES
	 */

	public static List<CountryDetail> getAllCountries() {
		Object cacheObject = memcache.get(_countries);
		return cacheObject != null ? (List<CountryDetail>) cacheObject : null;

	}

	public static void putCountries(List<CountryDetail> countries) {
		try {

			memcache.put(_countries, countries, Expiration.byDeltaSeconds(8600));
		} catch (Exception ex) {

		}
	}

	public static void removeCountries() {
		memcache.delete(_countries);
	}

	public static CountryDetail getCountryByCode(String cCode) {
		Object cacheObject = memcache.get(_countries);
		if (cacheObject != null) {

			List<CountryDetail> list = (List<CountryDetail>) cacheObject;
			for (Iterator<CountryDetail> iterator = list.iterator(); iterator.hasNext();) {
				CountryDetail countryDetail = (CountryDetail) iterator.next();
				if (countryDetail.getCCode().equalsIgnoreCase(cCode)) {
					return countryDetail;
				}
			}
		}
		return null;

	}

	public static CountryDetail getCountryById(Integer id) {
		Object cacheObject = memcache.get(_countries);
		if (cacheObject != null) {

			List<CountryDetail> list = (List<CountryDetail>) cacheObject;
			for (Iterator<CountryDetail> iterator = list.iterator(); iterator.hasNext();) {
				CountryDetail countryDetail = (CountryDetail) iterator.next();
				if (countryDetail.getId().equals(new Long(id))) {
					return countryDetail;
				}
			}
		}
		return null;

	}

}
